package com.zhangyj.component;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.zhangyj.entitis.TreeItem;

public class TreeCreator {

	static public  class Node {
		public Node(TreeItem item) {
			this.item = item;
			this.parent = null;
			this.list = null;
		}

		TreeItem item;

		Node parent;

		List<Node> list;
	}

	private int[] coderules = null;
	String imagePath = null;
	Node root;
	int openNodeId =0;
	boolean showcode = false;

	public TreeCreator(List<TreeItem> items, String coderule, String imagePath) {
		initialize(items.iterator(), coderule, imagePath);
	}

	public TreeCreator(String coderule, String imagePath) {

		initialize(null, coderule, imagePath);

	}

	private void initialize(Iterator<TreeItem> items, String coderule, String imagePath) {
		if (imagePath.length() != 0) {
			if (imagePath.lastIndexOf("/") != (imagePath.length() - 1)) {
				imagePath = imagePath + "/";
			}
		}
		this.imagePath = imagePath;
		root = new Node(new TreeItem(0,0, null, null, false));

		if (coderule == null) {
			coderule = "2,2,2,2,2";
		}
		String arg[] = coderule.split(",", -1);
		coderules = new int[arg.length];
		for (int i = 0; i < arg.length; i++) {
			coderules[i] = Integer.parseInt(arg[i]);
		}

		if (items != null) {
			try {
				Node historyNode = null;
				while (items.hasNext()) {
					TreeItem item = items.next();
					historyNode = insertElement(item, historyNode);
				}
			} finally {
			}
		}
	}

	public Node insertElement(TreeItem item, Node historyItem) {

		int index = 0;
		int width = 0;
		int coderulesLength = coderules.length;
		while (true) {
			if (index < coderulesLength - 1) {
				width = width + coderules[index];

			} else {
				width = width + coderules[coderulesLength - 1];
			}
			index++;
			if (item.getCode().length() <= width) {
				break;
			}

		}
		Node node = new Node(item);
		if (historyItem == null) {

			node.item = item;
			addNode(root, node);
		} else {
			String historyCode = historyItem.item.getCode();
			int histroyCodeWidth = historyCode.length();
			if (index == 0) {
				addNode(root, node);
			} else {
				index = getIndexFromLeng(histroyCodeWidth);
				boolean isAdded = false;

				while (index >= 0) {
					int tempCode = 0;

					if (index < coderulesLength) {
						tempCode += coderules[index];
					} else {
						tempCode += coderules[coderulesLength - 1];
					}

					if (historyCode == null) {
						addNode(root, node);
						isAdded = true;
						break;
					} else if (((item.getCode().length() - historyCode.length()) <= tempCode) && item.getCode().startsWith(historyCode)) {

						addNode(historyItem, node);
						isAdded = true;
						break;
					} else {
						historyItem = historyItem.parent;
						historyCode = historyItem.item.getCode();
					}
					index--;
				}
				if (!isAdded) {
					addNode(root, node);
				}
			}

		}
		return node;
	}

	private int getIndexFromLeng(int len) {
		int index = 0;
		int width = 0;
		for (; index < coderules.length;) {
			width += coderules[index];
			if (len <= width) {
				break;
			}
			index++;
		}
		return index;
	}

	public String getXML() {
		StringBuffer buffer = new StringBuffer(1024);
		buffer.append("<root>");
		if (root.list != null && !root.list.isEmpty()) {
			Iterator<Node> iterator = root.list.iterator();
			while (iterator.hasNext()) {
				buildXml(iterator.next(), buffer);
			}
		}
		buffer.append("</root>");
		return buffer.toString();
	}

	public String getHTMLTree() {
		return this.getHTMLTree(false);
	}

	public String getHTMLTree(boolean hasCheckBox) {
		if (root == null || root.list == null)
			return "";
		StringBuilder buffer = new StringBuilder(1024);

		List<Node> list = root.list;
		int size = list.size();
		String state[] = new String[0];
		for (int i = 0; i < size; i++) {
			if ((i + 1) == size) {
				writeHtml(buffer, list.get(i), state, true, false, hasCheckBox);
			} else {
				writeHtml(buffer, list.get(i), state, false, false, hasCheckBox);
			}
		}
		return buffer.toString();
	}

	private void writeHtml(StringBuilder buffer, Node node, String[] state, boolean isEnd, boolean isHidden, boolean hasCheckBox) {
		buffer.append("<div");
		if (isHidden) {
			buffer.append(" style=\"display:none\"");
		}
		buffer.append(">");

		List<Node> list = node.list;
		int size = list == null ? 0 : list.size();
		// 如果有子结点为true
		boolean hasChilds = false;
		if (size > 0) {
			hasChilds = true;
		}

		int len = state.length;
		// 下一个结点的状态
		String nextState[] = new String[len + 1];
		for (int i = 0; i < len; i++) {
			nextState[i] = state[i];
			buffer.append("<img align=\"absmiddle\"");
			if ("I".equals(state[i])) {
				buffer.append(" src=\"" + imagePath + "I.gif\"");
			} else {
				buffer.append(" src=\"" + imagePath + "blank.gif\"");
			}
			buffer.append("/>");
		}

		nextState[len] = "I";
		buffer.append("<img");
		buffer.append(" align=\"absmiddle\"");
		/*
		 * 如果是打开的结点，openImg是m ,否则是空
		 */
		// 如果是最后一个
		if (isEnd) {
			// 如果是有子结点
			if (hasChilds) {
				nextState[len] = " ";
					buffer.append(" src=\"" + imagePath + "Lp.gif\"");
			} else {
				buffer.append(" src=\"" + imagePath + "L.gif\"");
			}
		} else {
			if (hasChilds) {
					buffer.append(" src=\"" + imagePath + "Tp.gif\"");
			} else {
				buffer.append(" src=\"" + imagePath + "T.gif\"");
			}
		}
		buffer.append("/>");

		if (hasCheckBox)
			buffer.append("<input  class=\"treeCheckBox\" type=\"checkbox\" name=\"\"/>");

		// 是否是叶子结点
		boolean leaf = node.item.isLeaf();
		if (leaf) {
			buffer.append("<img align=\"absmiddle\" src=\"" + imagePath + "leaf.gif\"/>");
		} else {
			buffer.append("<img align=\"absmiddle\" src=\"" + imagePath + "nleaf.gif\"/>");
		}

		String className = "treectn";
		int id = node.item.getId();
		String code = node.item.getCode();

		if (id==openNodeId)
			className = "treectn_s";

		buffer.append("<span class=\"").append(className).append("\" value =\"").append(node.item.getId()).append("\" nid=\"").append(id)
				.append("\" code=\"").append(code).append("\" leaf=\"").append(leaf).append("\">");

		buffer.append(node.item.getDescription());
		if (showcode)
			buffer.append(" [").append(code).append("]");

		buffer.append("</span>");

		for (int i = 0; i < size; i++) {
			if ((i + 1) == size) {
				writeHtml(buffer, list.get(i), nextState, true, true, hasCheckBox);
			} else {
				writeHtml(buffer, list.get(i), nextState, false, true, hasCheckBox);
			}
		}
		buffer.append("</div>");
	}

	private void buildXml(Node node, StringBuffer buffer) {
		addItem(buffer, node.item);
		if (node.list != null && !node.list.isEmpty()) {
			Iterator<Node> iterator = node.list.iterator();
			while (iterator.hasNext()) {
				buildXml(iterator.next(), buffer);
			}
		}
		buffer.append("</item>");
	}

	private void addItem(StringBuffer buffer, TreeItem item) {
		buffer.append("<item id=\"");
		buffer.append(item.getId());
		buffer.append("\" code=\"");
		buffer.append(item.getCode());
		buffer.append("\" description=\"");
		buffer.append(item.getDescription());
		buffer.append("\" isLeaf=\"");
		buffer.append(item.isLeaf());
		buffer.append("\">");
	}

	private void addNode(Node parentNode, Node node) {
		if (parentNode.list == null) {
			parentNode.list = new ArrayList<Node>();
		}
		node.parent = parentNode;
		parentNode.list.add(node);
	}

	public static void main(String arg[]) {
		List<TreeItem> list = new ArrayList<TreeItem>();
		list.add(new TreeItem(0,1, "01", "a1", false));
		list.add(new TreeItem(0,1, "0101", "a1", true));
		list.add(new TreeItem(0,1, "0112", "a1", true));
		list.add(new TreeItem(0,1, "0113", "a1", true));
		list.add(new TreeItem(0,1, "02", "a1", false));
		list.add(new TreeItem(0,1, "0201", "a1", true));
		list.add(new TreeItem(0,1, "0212", "a1", false));
		list.add(new TreeItem(0,1, "021201", "a1", true));
		list.add(new TreeItem(0,1, "021202", "a1", true));
		long a = System.currentTimeMillis();
		TreeCreator creater = new TreeCreator(list, "2,2,2,2", "/boast/common/images/");
		String xml = creater.getHTMLTree();
		System.out.println(System.currentTimeMillis() - a);
		System.out.println(xml);
	}
}
